#pragma once

#include<iostream>
#include<stdio.h>
#include<time.h>
#include<string>
#include<cstdarg>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>


#define SIZE 1024
#define LOGFILE "log.txt"

#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4

#define SCREEN    0
#define ONEFILE   1
#define CLASSFILE 2

class Log
{
public:
    Log()
    {
        printMethod = SCREEN;
        path = "./log/";
    }

    void enable(int method)
    {
        printMethod = method;
    }

    std::string leveltostr(int level)
    {
        switch(level)
        {
            case Info: return "Info";
            case Debug: return "Debug";
            case Warning: return "Waring";
            case Error: return "Error";
            case Fatal: return "Fatal";
            default: return "None";
        }
        
    }
    
    // void logmessage(int level, const char *format, ...)
    // {
    //      time_t t = time(nullptr);
    //      struct tm *ctime = localtime(&t);
    //      char leftbuffer[SIZE];
    //      snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", leveltostr(level).c_str(),
    //               ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
    //               ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
    
    //     va_list s;
    //     va_start(s, format);
    //     char rightbuffer[SIZE];
    //     vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
    //     va_end(s);  
    
    //      // 格式：默认部分+自定义部分
    //     char logtxt[SIZE * 2];
    //      snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);
    
    //      //printf("%s", logtxt); // 暂时打印
    //     printlog(level,logtxt);
    // }
    void printlog(int level,const std::string& logtxt)
    {
        switch(printMethod)
        {
            case SCREEN:
                std::cout << logtxt << std::endl;
            break;
            case ONEFILE:
            printonefile(LOGFILE,logtxt);
            break;
            case CLASSFILE:
            printclassfile(level,logtxt);
            break;
        }
    }

    void printonefile(const std::string &logname, const std::string& logtxt)
    {
        std::string _logname = path + logname; 
        int fd = open(_logname.c_str(),O_WRONLY|O_CREAT|O_APPEND,0666);
        if(fd < 0) 
            return;
        write(fd,logtxt.c_str(),logtxt.size());

        close(fd);
    }

    void printclassfile(int level, const std::string& logtxt)
    {
        std::string filename = logtxt;
        filename += ".";
        filename += leveltostr(level);
        printonefile(filename, logtxt);
    }

    void operator ()(int level, const char *format, ...)
    {
        time_t t = time(nullptr);
         struct tm *ctime = localtime(&t);
         char leftbuffer[SIZE];
         snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", leveltostr(level).c_str(),
                  ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                  ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
    
        va_list s;
        va_start(s, format);
        char rightbuffer[SIZE];
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);  
    
         // 格式：默认部分+自定义部分
        char logtxt[SIZE * 2];
         snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);
    
         //printf("%s", logtxt); // 暂时打印
        printlog(level,logtxt);
    }
    ~Log()
    {}
private:
    int printMethod;
    std::string path;
};
